package com.hzncc.flowable_diboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.binding.QueryBuilder;
import com.diboot.core.service.impl.BaseServiceImpl;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.S;
import com.diboot.core.util.SqlExecutor;
import com.diboot.core.util.V;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Pagination;
import com.diboot.iam.entity.IamUser;
import com.diboot.iam.service.IamUserService;
import com.diboot.iam.util.IamSecurityUtils;
import com.diboot.notification.config.Cons;
import com.diboot.notification.entity.Message;
import com.hzncc.flowable_diboot.dto.ClueDTO;
import com.hzncc.flowable_diboot.entity.Clue;
import com.hzncc.flowable_diboot.entity.ClueUser;
import com.hzncc.flowable_diboot.entity.ToDoList;
import com.hzncc.flowable_diboot.mapper.ClueMapper;
import com.hzncc.flowable_diboot.mapper.ClueUserMapper;
import com.hzncc.flowable_diboot.rabbitmq.service.impl.SendMessageService;
import com.hzncc.flowable_diboot.service.ClueService;
import com.hzncc.flowable_diboot.service.ToDoListService;
import com.hzncc.flowable_diboot.util.ConstantUtil;
import com.hzncc.flowable_diboot.vo.ClueListVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 线索 相关Service实现类
 *
 * @author MyName
 * @version 1.0
 * @date 2024-06-06
 * Copyright © MyCorp
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ClueServiceImpl extends BaseServiceImpl<ClueMapper, Clue> implements ClueService {

    private final CommonService commonService;

    private final SendMessageService sendMessageService;

    private final ClueUserMapper clueUserMapper;

    private final IamUserService userService;

    private final ToDoListService toDoListService;

    @Override
    protected void afterCreate(Clue entity) {
        createOrUpdateN2NRelations(ClueUser::getClue, entity.getId(), ClueUser::getUser, entity.getStarUids());
    }

    @Override
    protected void afterUpdate(Clue entity) {
        createOrUpdateN2NRelations(ClueUser::getClue, entity.getId(), ClueUser::getUser, entity.getStarUids());
    }

    /**
     * 线索查询
     *
     * @param queryDto
     * @param pagination
     * @param type
     * @return
     */
    public JsonResult<List<ClueListVO>> selectClue(ClueDTO queryDto, Pagination pagination, String type) {
        if (pagination != null && V.isEmpty(pagination.getOrderBy())) {
            pagination.setOrderBy(Pagination.ORDER_BY_ID_DESC);
        }
        // 已转化的线索
        if (Objects.equals("used", type)) {
            queryDto.setStatus("used");
        }
        QueryWrapper<Clue> queryWrapper = QueryBuilder.toQueryWrapper(queryDto, pagination);
        if(!commonService.isCrossTenant(IamSecurityUtils.getCurrentTenantId())) {
            // 我的线索
            if (Objects.equals("resp", type)) {
                queryDto.setUid(IamSecurityUtils.getCurrentUserId());
                queryWrapper.eq("uid", queryDto.getUid());
            }
            if (!Objects.equals("used", type)) {
                queryWrapper.ne("status", "used");
            }
            // 下属负责的线索
            if (Objects.equals("sub", type)) {
                List<String> subEmp = commonService.findSubEmp(IamSecurityUtils.getCurrentUser());
                if (subEmp.isEmpty()) {
                    return JsonResult.OK();
                }
                queryWrapper.in("uid", subEmp);
            }
            // 全部线索
            if (Objects.equals("self", type)) {
                List<String> subEmp = commonService.findSubEmp(IamSecurityUtils.getCurrentUser());
                subEmp.add(IamSecurityUtils.getCurrentUserId());
                queryWrapper.in("uid", subEmp);
            }
            // 我关注的线索
            if (Objects.equals("star", type)) {
                List<String> ids = clueUserMapper.selectStar(IamSecurityUtils.getCurrentUserId());
                if (ids == null || ids.isEmpty()) {
                    return JsonResult.OK();
                }
                queryWrapper.in("id", ids);
            }
        }
        List<ClueListVO> viewObjectList = getViewObjectList(queryWrapper, pagination, ClueListVO.class);
        for (ClueListVO datum : viewObjectList) {
            if (datum.getStarUids() != null && datum.getStarUids().contains(IamSecurityUtils.getCurrentUserId())) {
                datum.setIsStar(1);
            } else {
                datum.setIsStar(0);
            }
        }
        return JsonResult.OK(viewObjectList).bindPagination(pagination);
    }

    @Transactional
    @Override
    public void trans(String uid, List<String> ids) {
        List<Clue> clues = getEntityListByIds(ids);
        for (Clue clue : clues) {
            clue.setUid(uid);
        }
        updateEntities(clues);
        //清除关注
        clueUserMapper.del(IamSecurityUtils.getCurrentUserId(), "'" + S.join(ids, "','") + "'");
        // 消息
        IamUser user = IamSecurityUtils.getCurrentUser();
        Message msg = new Message();
        msg.setAppModule(ConstantUtil.MODEL_SALES);
        msg.setSender(IamSecurityUtils.getCurrentUserId());
        msg.setTitle("线索转移");
        msg.setContent(S.format(ConstantUtil.CLUE_TRANSACTION_MSG_TEMPLATE, user.getRealname(), clues.stream()
                .map(Clue::getName)
                .collect(Collectors.joining(","))));
        msg.setReceiver(uid);
        msg.setTemplateId("");
        msg.setBusinessCode("");
        msg.setBusinessType("");
        msg.setChannel(Cons.MESSAGE_CHANNEL.SYS_MSG.name());
        msg.setStatus(Cons.MESSAGE_STATUS.PENDING.name());
        sendMessageService.sendRetainedMessage(msg);
    }

    @Override
    public void distribute(String uid, List<String> ids) {
        List<Clue> clues = getEntityListByIds(ids);

        clues.forEach(clue -> {
            clue.setUid(uid);
            clue.setFlag(1);
            clue.setDisDate(LocalDateTime.now()); // 分配时间

        });
        updateEntities(clues);
        // 发送消息
        IamUser dis = userService.getEntity(IamSecurityUtils.getCurrentUserId());
        Message msg = new Message();
        msg.setAppModule(ConstantUtil.MODEL_SALES);
        msg.setReceiver(uid);
        msg.setTitle("线索分配");
        msg.setSender(uid);
        msg.setContent(String.format(ConstantUtil.CLUE_DIS_MSG_TEMPLATE, dis.getRealname(), S.join(BeanUtils.collectToList(clues, Clue::getName))));
        msg.setChannel(Cons.MESSAGE_CHANNEL.SYS_MSG.name());
        msg.setStatus(Cons.MESSAGE_STATUS.DELIVERY.name());
        msg.setTemplateId("");
        msg.setBusinessType("");
        msg.setBusinessCode("");
        sendMessageService.sendRetainedMessage(msg);
        List<ToDoList> toDoLists = new ArrayList<>();
        for (Clue clue : clues) {
            toDoLists.add(new ToDoList().setType(ConstantUtil.DIS_CLUE)
                    .setClueId(clue.getId())
                    .setExecutor(uid)
                    .setDisTime(LocalDateTime.now())
                    .setContactWay(clue.getContactWay())
                    .setHasMsg(true)
                    .setModel(ConstantUtil.MODEL_SALES));
        }
        toDoListService.createToDo(toDoLists);
    }

    @Override
    public JsonResult<?> checkClue(String id) {
        if (S.equals(getEntity(id).getStatus(), "used")) {
            return JsonResult.FAIL_INVALID_PARAM("已转化，不能继续操作!");
        }
        return JsonResult.OK();
    }


    /**
     * 线索跟进检测
     *
     * @author 陈广煜
     * @date 2024/6/13
     */
    public void checkFollowTime() throws Exception {
        String exp = "select * from mdl_clue where expiration_time = 0 and is_deleted = 0 and flag = 1 and status != 'used'";
        List<Clue> clues = SqlExecutor.getJdbcTemplate().query(exp, BeanPropertyRowMapper.newInstance(Clue.class));
        //baseMapper.updateExpire(); // 更新据进入公海天数
        String sql = "update mdl_clue set expiration_time = expiration_time - 1 where is_deleted = 0 and expiration_time > 0";
        SqlExecutor.executeUpdate(sql, null);
        String enterDays = "update mdl_clue set enter_days = enter_days + 1 where flag = 0 and is_deleted = 0";
        SqlExecutor.executeUpdate(enterDays, null);
        if (clues.isEmpty()) {
            return;
        }
        List<String> ids = BeanUtils.collectToList(clues, Clue::getId);
        String updateClues = "update mdl_clue set flag = 0,enter_time = now(),reason='长时间未跟进，系统自动置入线索池',uid=null where id in ('" + String.join("','", ids) + "')";
        SqlExecutor.executeUpdate(updateClues, null);
    }
}